package ai.plantdata.dao.strategy.impl;

import ai.plantdata.constant.TableEnum;
import ai.plantdata.dao.dto.AssociateDTO;
import ai.plantdata.dao.dto.EntityExpandTable;
import ai.plantdata.dao.strategy.SeparateHandle;
import ai.plantdata.dao.util.JdbcUtils;
import ai.plantdata.graph.api.Node;
import ai.plantdata.graph.api.Property;
import ai.plantdata.graph.api.schema.ConceptDefinition;
import ai.plantdata.graph.api.schema.NumericDefinition;
import ai.plantdata.graph.mongo.MongoGraphStore;
import ai.plantdata.vo.DataSourceConfig;
import ai.plantdata.dao.util.BeanTransform;
import ai.plantdata.util.SeparateStrategyUtils;
import ai.plantdata.vo.SeparateTable;
import org.springframework.util.CollectionUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Author: WangHui
 * @Date: 2021/7/19 10:38
 * @Description:
 */
public class EntityExpand implements SeparateHandle {
    @Override
    public List<ConceptDefinition> schemaHandle(SeparateTable separateDTO, DataSourceConfig dataSourceConfig, MongoGraphStore store) {
        EntityExpandTable table = BeanTransform.separateTableToEntityExpandTable(separateDTO);
        List<String> filedNames = table.getFiledNames();
        String tableName = table.getTableName();
        Connection conn = JdbcUtils.getConnection(dataSourceConfig);
        List<NumericDefinition> numDef = getNumDef(conn, tableName, filedNames);
        TableEnum tableEnum = table.getTableEnum();
        SeparateHandle select = SeparateStrategyUtils.select(tableEnum);
        List<ConceptDefinition> tokens = select.schemaHandle(separateDTO, dataSourceConfig, store);
        for (ConceptDefinition token : tokens) {
            token.setAttributes(numDef);
        }
        if (!CollectionUtils.isEmpty(tokens)) {
            store.saveSchema(tokens);
        }
        return tokens;
    }

    @Override
    public void entityHandle(SeparateTable separateDTO, DataSourceConfig dataSourceConfig, MongoGraphStore store) {
        try {
            EntityExpandTable table = BeanTransform.separateTableToEntityExpandTable(separateDTO);
            List<String> fieldName = table.getFiledNames();
            String tableName = table.getTableName();
            AssociateDTO associateDTO = table.getAssociateDTO();
            String associationField = table.getAssociationField();
            Connection conn = JdbcUtils.getConnection(dataSourceConfig);

            if (CollectionUtils.isEmpty(fieldName)) {
                fieldName = new ArrayList<>();
            }
            StringBuilder str = new StringBuilder();
            for (String s : fieldName) {
                str.append(" , ").append(s);
            }
            String sql;
            sql = "select %s %s from %s";
            sql = String.format(sql, associationField, str, tableName);
            PreparedStatement ps = conn.prepareStatement(sql);
            ResultSet rs = ps.executeQuery();
            List<Node> nodes = new ArrayList<>();
            while (rs.next()) {
                Object obj = rs.getObject(1);
                Map<String, String> map = getAssociate(conn, associateDTO, obj);
                if (map == null) {
                    throw new RuntimeException("关联的实体不存在");
                }
                Node node = Node.create(map.get("name"), map.get("meanTag"));
                List<Property> properties = new ArrayList<>();
                for (int i = 0; i < fieldName.size(); i++) {
                    Property property = Property.create(fieldName.get(i), rs.getObject(2 + i));
                    properties.add(property);
                }
                node.setProperties(properties);
                nodes.add(node);
                if (nodes.size() % 10_000 == 0) {
                    //保存关系
                    store.saveNodeWithProperty(nodes);
                    nodes.clear();
                }
            }
            JdbcUtils.close(ps, rs);
            if (!nodes.isEmpty()) {
                store.saveNodeWithProperty(nodes);
                nodes.clear();
            }
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
